package adoku.analyze ;

import java_cup.runtime.* ;
import java.util.HashMap ;
import java.util.ArrayList ;
      
%%
   
%class LexicalAnalyzer
%public

%line
%column
%unicode
    
%type Symbol
%eofval{
  return symbol(LexicalUnits.EOF) ;
%eofval}

%cupsym LexicalUnits
%cup
   
%{
  private StringBuilder buffer ;
  private StringBuilder nowikiBuffer ;
  private ArrayList foundFormats = new ArrayList<String>();
  private int previousState ;


  private HashMap<String,Integer> formats = new HashMap() {
    {
        put("**",LexicalUnits.BOLD);
        put("//",LexicalUnits.ITALIC);
        put("__",LexicalUnits.UNDERLINED);
        put("\"",LexicalUnits.MONOSPACE);
        put("<sup>",LexicalUnits.SUPERSCRIPT);
        put("</sup>",LexicalUnits.SUPERSCRIPT);
        put("<sub>",LexicalUnits.SUBSCRIPT);
        put("</sub>",LexicalUnits.SUBSCRIPT);
        put("<del>",LexicalUnits.STRUCK);
        put("</del>",LexicalUnits.STRUCK);
    }
  };


  private String s ;

	private Symbol symbol(int type) {
		return new Symbol(type, yyline, yycolumn) ;
	}
	
	private Symbol symbol(int type, Object value) {
		return new Symbol(type, yyline, yycolumn, value) ;
	}

%}

%state Paragraph
%state Title
%state Equal
%state Table
%state List
//SM -----------
%state Nowiki
//SM -----------


Bold = \*\*
Italic = \/{2}
Underlined = __
Monospace = \"
StartSuperScript = "<sup>"
EndSuperScript = "</sup>"
StartSubScript = "<sub>"
EndSubScript = "</sub>"
StartStruck = "<del>"
EndStruck = "</del>"
FootNote = [(]{2}[^]*[)]{2}
HyperTextLink = [\[]{2}[^\[\]]*[|][^\[\]|]*[\]]{2} | "http://"[^ \\]* | "https://"[^ \\]* | "ftp://"[^ \\]*
Paragraph = \n\n+
MailLink = [<][^<>]*[@][^<>]*[.][^<>]*[>]
Format =  {Bold}|{Italic}|{Underlined}|{Monospace}|{StartSuperScript}|{EndSuperScript}|{StartSubScript}|{EndSubScript}|{StartStruck}|{EndStruck}
StartTitle = [=]+
EndTitle = [=]{2,6}
Text = [^()\[\]\%=\-\n*_/\"<|\^\\:]*
Paragraph = \n\n+
HeaderCell = \^
Cell = \|
Colspan = [\^|][\^|]+
SpecialChar = [_][_]+ | \| | \/ | \" | "[" | "]" | "<" | ">" | "(" | ")" | [_] | ":" | "%"
BulletList = [ ]{2}+[*]
NumberedList = [ ]{2}+[-]
List =  {BulletList} | {NumberedList}
LineBreak = [\\]{2}[ ] | [\\]{2}[\n] | [\\]{2}"\r\n"
HorizontalSeparator = [-][-][-][-]+
Notoc = "~~NOTOC~~"
//Nowiki = "<nowiki>"[^]*"</nowiki>" | "%%"[^]*"%%"
// SM -----------
NowikiStart = "<nowiki>"  | "%%"
NowikiEnd   = "</nowiki>" | "%%"
// SM -----------

Linefeed = \n

/* A line terminator is a \r (carriage return), \n (line feed), or \r\n. */
LineTerminator = \r|{Linefeed}|\r{Linefeed}


/* White space is a line terminator, space, tab, or line feed. */
WhiteSpace     = {LineTerminator} | [ \t\f]

%%

/*
 * Initial state
 */
<YYINITIAL> {Notoc}     {
                            return symbol(LexicalUnits.NOTOC);
                        }

<YYINITIAL>  "="        {
                            buffer = new StringBuilder();
                            buffer.append(yytext());
                            yybegin(Equal);
                        }

<YYINITIAL> {Cell} | {HeaderCell}       {
                                            yybegin(Table);
                                            return symbol(LexicalUnits.CELL,yytext());
                                        }

<YYINITIAL> {Paragraph} | {LineTerminator}{LineTerminator}+ {
                            return symbol(LexicalUnits.PARAGRAPH_SEPARATOR);
			}

<YYINITIAL> {Format}    {
                            yybegin(Paragraph);
                            return symbol(formats.get(yytext()));
                        }

<YYINITIAL> {HyperTextLink}     {
                                    return symbol(LexicalUnits.HYPERTEXT_LINK,yytext());
                                }

// SM -----------
/*
<YYINITIAL> {Nowiki}    {   
                            s = yytext();
                            if(s.startsWith("<nowiki>")) {
                                s = s.substring(s.indexOf("<nowiki>")+8,s.indexOf("</nowiki>"));
                            }else if(s.startsWith("%")) {
                                s = s.substring(1,s.length()-2);
                            }
                            return symbol(LexicalUnits.TEXT,s);
                        }
*/
//SM -----------

<YYINITIAL, Paragraph, Table, List> {NowikiStart}
{
	previousState = this.zzLexicalState ;
	yybegin(Nowiki) ;
	nowikiBuffer = new StringBuilder() ;
//	System.out.printf("Start nowiki state from state %d ...\n'", previousState) ;
}

<Nowiki> {NowikiEnd}
{
	yybegin(previousState) ;
//	System.out.printf("'\nEnd nowiki state ...\n\treturn '%s'\n\treturn to %d\n", buffer.toString(), previousState) ;
	return symbol(LexicalUnits.TEXT, nowikiBuffer.toString()) ;
}

<Nowiki> . | {WhiteSpace}
{
//	System.out.print(this.yytext()) ;
	nowikiBuffer.append(this.yytext()) ;
}

<YYINITIAL> {Text}    {
                            s = yytext();
                            if(s.endsWith("http") || s.endsWith("https") || s.endsWith("ftp")) {
                                buffer = new StringBuilder();
                                if(s.endsWith("http")){
                                    s = s.substring(0,s.lastIndexOf("http"));
                                    buffer.append("http");
                                }else if(s.endsWith("https")) { 
                                    s = s.substring(0,s.lastIndexOf("https"));
                                    buffer.append("https");
                                }else if(s.endsWith("ftp")) {
                                    s = s.substring(0,s.lastIndexOf("ftp"));
                                    buffer.append("ftp");
                                }
                            }
                            yybegin(Paragraph);
                            return symbol(LexicalUnits.TEXT,s);
			}

<YYINITIAL> {List}        {
                            s = yytext() ;
                            yybegin(List);
                            return symbol(LexicalUnits.LIST_LVL,s);
                          }

<YYINITIAL> "-" | "*"
{
	return symbol(LexicalUnits.TEXT, this.yytext()) ;
}

<YYINITIAL> {MailLink}  {
                            return symbol(LexicalUnits.MAIL_LINK,yytext());
                        }

<YYINITIAL> {FootNote}      {
                                return symbol(LexicalUnits.FOOTNOTE,yytext());
                            }


<YYINITIAL> {SpecialChar}    { 
                                  return symbol(LexicalUnits.TEXT,yytext());
                              }


<YYINITIAL> {LineBreak}     {
                                return symbol(LexicalUnits.LINEBREAK);
                            }

<YYINITIAL> {HorizontalSeparator}   {
                                        return symbol(LexicalUnits.HORIZONTAL_SEPARATOR) ;
                                    }

/*
 * In case of a paragraph
 */

<Paragraph> {Paragraph} | {LineTerminator}{LineTerminator}+ {
                            yybegin(YYINITIAL);
                            return symbol(LexicalUnits.PARAGRAPH_SEPARATOR);
			}

<Paragraph> {Format}    {
                            return symbol(formats.get(yytext()));  
                        }

<Paragraph> {HyperTextLink}     {
                                    return symbol(LexicalUnits.HYPERTEXT_LINK,yytext());
                                }

// SM -----------------------
<Paragraph> /*"://"[^ \n\r]+*/"://"[a-zA-Z0-9]+"."[^ \n\r]+  {
                                s = yytext() ;
                                if(buffer != null) {
                                    s = buffer.toString() + s ;
                                    buffer = null ;
                                }
                                return symbol(LexicalUnits.HYPERTEXT_LINK,s);
                            }

// SM -------------
/*
<Paragraph> {Nowiki}    {   
                            s = yytext();
                            if(s.startsWith("<nowiki>")) {
                                s = s.substring(s.indexOf("<nowiki>")+8,s.indexOf("</nowiki>"));
                            }else if(s.startsWith("%")) {
                                s = s.substring(1,s.length()-2);
                            }
                            return symbol(LexicalUnits.TEXT,s);
                        }
*/
// SM ------------

<Paragraph> [^\:()\[\]\%=\n*_/\"<\\]*  {
                                        s = yytext();
                                        if(s.endsWith("http") || s.endsWith("https") || s.endsWith("ftp")) {
                                            buffer = new StringBuilder();
                                            if(s.endsWith("http")){
                                                s = s.substring(0,s.lastIndexOf("http"));
                                                buffer.append("http");
                                            }else if(s.endsWith("https")) { 
                                                s = s.substring(0,s.lastIndexOf("https"));
                                                buffer.append("https");
                                            }else if(s.endsWith("ftp")) {
                                                s = s.substring(0,s.lastIndexOf("ftp"));
                                                buffer.append("ftp");
                                            }
                                            buffer.append(s);
                                        }
                                        return symbol(LexicalUnits.TEXT,s);
                                    }

<Paragraph> {MailLink}      {
                                return symbol(LexicalUnits.MAIL_LINK,yytext());
                            }

<Paragraph> {FootNote}      {
                                return symbol(LexicalUnits.FOOTNOTE,yytext());
                            }

<Paragraph>  {StartTitle}   { 
                                return symbol(LexicalUnits.TEXT,yytext());
                            }

<Paragraph> {LineBreak}     {
                                return symbol(LexicalUnits.LINEBREAK);
                            }

<Paragraph> {SpecialChar} | "*"   {
                                            return symbol(LexicalUnits.TEXT,yytext());
                                        }


/*
 * If the analyser meet one or more "=" 
 * decides if it's a title or just text
 */

<Equal> {StartTitle}    {
                            s = buffer.toString() + yytext() ;
                            buffer = null ;
                            if(s.length() > 1 && s.length() < 7) {
                                yybegin(Title);
                                return symbol(LexicalUnits.TITLE, s);
                            }else{
                                yybegin(Paragraph);
                                return symbol(LexicalUnits.TEXT, s);
                            }
                        }

/*
 * In case of Title
 */


<Title> [^=\n]*         {
                            return symbol(LexicalUnits.TEXT, yytext());
                        }

<Title> {EndTitle}      {
                            return symbol(LexicalUnits.TITLE,yytext());
                        }

<Title> {Paragraph} | {LineTerminator}{LineTerminator}+	{
                            yybegin(YYINITIAL); 
                            return symbol(LexicalUnits.PARAGRAPH_SEPARATOR);
			}

/*
 * In case of Table
 */

<Table> {Cell} | {HeaderCell}        {
                                        return symbol(LexicalUnits.CELL,yytext());
                                     }

<Table> {Format}        {
                            return symbol(formats.get(yytext()));  
                        }

<Table> {HyperTextLink}     {
                                return symbol(LexicalUnits.HYPERTEXT_LINK,yytext());
                            }

<Table> "://"[^ ]*      {
                                s = yytext() ;
                                if(buffer != null) {
                                    s = buffer.toString() + s ;
                                    buffer = null ;
                                }
                                return symbol(LexicalUnits.HYPERTEXT_LINK,s);
                        }

// SM ---------------
/*
<Table> "<nowiki>"[^\|\^]*"</nowiki>" | "%"[^\%\|\^]*"%"    {
                        s = yytext();
                        if(s.startsWith("<nowiki>")) {
                            s = s.substring(s.indexOf("<nowiki>")+8,s.indexOf("</nowiki>"));
                        }else if(s.startsWith("%")) {
                            s = s.substring(1,s.length()-2);
                        }
                        return symbol(LexicalUnits.TEXT,s);
                    }
*/
// SM ------------------

<Table> [ \t]*":::"[ \t]*   {
                                return symbol(LexicalUnits.ROWSPAN);
                            }

<Table> {Text}          {
                           s = yytext();
                           if(s.endsWith("http") || s.endsWith("https") || s.endsWith("ftp")) {
                                buffer = new StringBuilder();
                                if(s.endsWith("http")){
                                    s = s.substring(0,s.lastIndexOf("http"));
                                    buffer.append("http");
                                }else if(s.endsWith("https")) { 
                                    s = s.substring(0,s.lastIndexOf("https"));
                                    buffer.append("https");
                                }else if(s.endsWith("ftp")) {
                                    s = s.substring(0,s.lastIndexOf("ftp"));
                                    buffer.append("ftp");
                                }
                                buffer.append(s);
                           }
                           return symbol(LexicalUnits.TEXT,s);
                        }

<Table> {MailLink}  {
                        return symbol(LexicalUnits.MAIL_LINK,yytext());
                    }

<Table> {FootNote}      {
                                return symbol(LexicalUnits.FOOTNOTE,yytext());
                        }

<Table> {LineBreak}     {
                                return symbol(LexicalUnits.LINEBREAK);
                            }

<Table> {SpecialChar} | "-"  | "*"   {
                                    return symbol(LexicalUnits.TEXT,yytext());
                                }

<Table> {Paragraph} | {LineTerminator}{LineTerminator}+ {
                            yybegin(YYINITIAL); 
                            return symbol(LexicalUnits.PARAGRAPH_SEPARATOR);
			}

<Table> {Linefeed}      {
                            return symbol(LexicalUnits.LINEFEED);
                        }

<Table> {Colspan}       {
                            return symbol(LexicalUnits.COLSPAN, yytext());
                        }


/*
 * In case of a list
 */

<List> {List}           {
                            return symbol(LexicalUnits.LIST_LVL, yytext());
                        }

<List> {HyperTextLink}  {
                            return symbol(LexicalUnits.HYPERTEXT_LINK,yytext());
                        }

<List> "://"[^ ]*      {
                                s = yytext() ;
                                if(buffer != null) {
                                    s = buffer.toString() + s ;
                                    buffer = null ;
                                }
                                return symbol(LexicalUnits.HYPERTEXT_LINK,s);
                       }

// SM ---------------
/*
<List> {Nowiki}    {
                        s = yytext();
                        if(s.startsWith("<nowiki>")) {
                            s = s.substring(s.indexOf("<nowiki>")+8,s.indexOf("</nowiki>"));
                        }else if(s.startsWith("%")) {
                            s = s.substring(1,s.length()-2);
                        }
                        return symbol(LexicalUnits.TEXT,s);
                   }
*/
//SM ---------------

<List> {Text}           {
                           s = yytext();
                           if(s.endsWith("http") || s.endsWith("https") || s.endsWith("ftp")) {
                                buffer = new StringBuilder();
                                if(s.endsWith("http")){
                                    s = s.substring(0,s.lastIndexOf("http"));
                                    buffer.append("http");
                                }else if(s.endsWith("https")) { 
                                    s = s.substring(0,s.lastIndexOf("https"));
                                    buffer.append("https");
                                }else if(s.endsWith("ftp")) {
                                    s = s.substring(0,s.lastIndexOf("ftp"));
                                    buffer.append("ftp");
                                }
                                buffer.append(s);
                           }
                           return symbol(LexicalUnits.TEXT,s);
                        }

<List> {MailLink}       {
                            return symbol(LexicalUnits.MAIL_LINK,yytext());
                        }

<List> {FootNote}      {
                                return symbol(LexicalUnits.FOOTNOTE,yytext());
                       }

<List> {Format}         {
                            return symbol(formats.get(yytext()));
                        }

<List> {Paragraph} | {LineTerminator}{LineTerminator}+ {
                            yybegin(YYINITIAL); 
                            return symbol(LexicalUnits.PARAGRAPH_SEPARATOR);
                        }

<List> {SpecialChar} | "-"  | "*" | "=" | "\\"   {
                                        return symbol(LexicalUnits.TEXT,yytext());
                                     }

{WhiteSpace}       				
{
  /* just skip what was found, do nothing */ 
} 
/* No token was found for the input so through an error.  Print out an
   Illegal character message with the illegal character that was found. */
 [^]                    			
 { throw new java.io.IOException("Échec de l'analyse du fichier doku. (caractère inattendu : '"+yytext()+"', état : "+zzLexicalState+" - "+yyline+", "+yycolumn+")\n"); }

